/**
 * This class is responsible to display and manage editable references of other item objects
 * @author zulianp@lu.unisi.ch
 */

package ch.unisi.inf.projects.java.uom.gui.itemeditor.fieldselector;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.HashSet;
import java.util.Iterator;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.BoxLayout;
import javax.swing.Box;

import ch.unisi.inf.projects.java.uom.Constants;
import ch.unisi.inf.projects.java.uom.Parser;
import ch.unisi.inf.projects.java.uom.elements.Item;
import ch.unisi.inf.projects.java.uom.elements.ItemClass;
import ch.unisi.inf.projects.java.uom.elements.ItemManager;
import ch.unisi.inf.projects.java.uom.exceptions.UOMException;
import ch.unisi.inf.projects.java.uom.gui.commands.EmptyStringCommand;
import ch.unisi.inf.projects.java.uom.gui.commands.ItemCreateCommand;
import ch.unisi.inf.projects.java.uom.gui.commands.LinkReferenceCommand;
import ch.unisi.inf.projects.java.uom.gui.commands.ReferenceChooseCommand;

public class ItemEntryGUI extends EntryGUI implements ItemListener{

	public static final int SELECT_REFERENCE = 1;
	public static final int DISPLAY_REFERENCE = 0;
	public static final int CREATE_REFERENCE = 2;
	private static final int LABEL = 3;
	private static final int ERROR_ITEMCLASS = 4;
	private final Component[] components; //to be initialize with the number of static fields
	private int entryStatusIndex;
	private final JPanel panel;
	private ItemClass itemClass;

	public ItemEntryGUI(final String key, final String value, final JPanel ContainerPanel, final Item item) {
		super(key, value, item);
		components = new Component[5];
		this.panel = new JPanel();
		//this.panel.setLayout(new GridLayout(1,1));
		this.panel.setLayout(new BoxLayout(this.panel, BoxLayout.Y_AXIS));
		this.panel.setBackground(getDefaultColor());
		setLabel();
		ContainerPanel.add(components[LABEL]);
		ContainerPanel.add(this.panel);
		this.panel.add(Box.createVerticalGlue());
		setUp();
		setLabelActions();
		this.panel.add(Box.createVerticalGlue());
	}
	
	
	private void  setLabel()
	{
		final PopupActionJLabel popupMenu = new PopupActionJLabel();
		popupMenu.setHorizontalAlignment(JLabel.RIGHT);
		components[LABEL] = popupMenu;
		try {
			popupMenu.setText(Parser.instance().dbGetVarName(key) + " : ");
		}
		catch (final UOMException ex)
		{
			popupMenu.setText("");
		}		
	}
	
	@SuppressWarnings("serial")
	private void setLabelActions()
	{
		PopupActionJLabel popupMenu = (PopupActionJLabel) components[LABEL]; 

		
		AbstractAction chooseReference = new AbstractAction() {
		public void actionPerformed(ActionEvent e) {
			if (entryStatusIndex == ERROR_ITEMCLASS)
				return;
				value = null;
				setModified(true);
				refresh();
				setModified(true);
				panel.revalidate();
				panel.repaint();}};
		chooseReference.putValue(AbstractAction.NAME, "Choose Reference");
		
		popupMenu.addAbstractAction(chooseReference);
	}
	
	public void setUp(){
		
		ItemManager manager = ItemManager.instance();
		boolean invalidRef = false;
		if((value != null) && !("".equals(value)) && (value.length() > 0)){
			Item referenceItem = null;		
			try {
				if (!key.contains(Constants.ITEM_PARSECHAR.value())) {
					final ItemClass c = manager.itemClassGet(key);
					if (c == null)
						invalidRef = true;
					else {
						referenceItem = manager.itemGet(value, c);
						value = key + Constants.ITEM_PARSECHAR.value() + value;
					}
				}
				else
					referenceItem = manager.itemGet(key,value);
				if (referenceItem == null)
					invalidRef = true;
			} catch (Exception e) {
				e.printStackTrace();
				invalidRef = true;
			}
			if (!invalidRef) {
				JButton referenceButton = new JButton(new LinkReferenceCommand(referenceItem));
				referenceButton.setBackground(getDefaultColor());
				//referenceButton.setBorder(new EmptyBorder(0,0,0,0));
				panel.add(referenceButton);
				entryStatusIndex = DISPLAY_REFERENCE;
				components[DISPLAY_REFERENCE] = referenceButton;
				return;
			}
		}
		if (value == null || value.equals("") || value.length() <= 0 || invalidRef)
		{	
			String[] splittedKey = key.split(Constants.ITEM_PARSECHAR.value());
			
			
			try {
					itemClass = manager.itemClassGet(splittedKey[0]);
					if (itemClass == null) {
						final JLabel errorLabel = new JLabel("Invalid reference category '" + splittedKey[0] + "'");
						this.setValue("");
						this.setModified(true);
						panel.add(errorLabel);
						components[ERROR_ITEMCLASS] = errorLabel;
						entryStatusIndex = ERROR_ITEMCLASS;
						return;
					}
					final HashSet<Item> relatedItems = (HashSet<Item>) manager.getItemsFromItemClass(itemClass);
					if(relatedItems.size() >= 1)
					{
						AbstractAction[] labels = new AbstractAction[relatedItems.size() + 1];
						int index = 1;
						labels[0] = new EmptyStringCommand(this,invalidRef);
							
						
						Iterator<Item> it = relatedItems.iterator();
						while(it.hasNext())
						{
							labels[index] = new ReferenceChooseCommand(it.next(),this);
							index++;
						}
						
						final JComboBox comboBox = new JComboBox(labels);
						comboBox.setEnabled(true);
						comboBox.addItemListener(this);
						comboBox.setBackground(getDefaultColor());
						panel.add(comboBox);
						entryStatusIndex = SELECT_REFERENCE;
						components[SELECT_REFERENCE] = comboBox;
						
					}
					else
					{
						final JButton createButton = new JButton(new ItemCreateCommand(itemClass,false));
						createButton.setBackground(getDefaultColor());      
						panel.add(createButton);
						entryStatusIndex = CREATE_REFERENCE;
						components[CREATE_REFERENCE] = createButton;
						
					}
			} catch (final Exception e) {
				// TODO Auto-generated catch block
				panel.add(new JLabel(e.getMessage()));
			}
			
		}
		
	}

	@Override
	public void select() {
		if(isModified()){
		JComboBox comboBox = (JComboBox)components[SELECT_REFERENCE];
		if(comboBox.getSelectedItem() == null) {
			value = "";
		}
		else {
				((AbstractAction) comboBox.getSelectedItem()).actionPerformed(null);
			}
		}
	}

	
	@Override
	public boolean setFromInput() {
		
		switch(entryStatusIndex) {
		case DISPLAY_REFERENCE : return true;
		case CREATE_REFERENCE  : return true;
		case SELECT_REFERENCE  : select();}
		return true;
	}

	public void itemStateChanged(final ItemEvent e) {
		this.setModified(true);
	}

	@Override
	protected void refresh() {
		if(isModified()) {
			panel.remove(panel.getComponent(panel.getComponentCount() - 1));
			panel.remove(components[entryStatusIndex]);
			setModified(false);
			setLabel();
			setUp();
			panel.add(Box.createVerticalGlue());
			panel.repaint();
		}
	}


	public int getEntryStatusIndex() {
		return entryStatusIndex;
	}


	public JPanel getPanel() {
		return panel;
	}
	
	

}
